package route

import (
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"reflect"
	"regexp"
	"strings"
	"sync"
	"think/app/controller"
	"think/common"
	"unicode"
)

// AutoRouter 自动路由注册器
type AutoRouter struct {
	router          *Router
	mutex           sync.RWMutex
	controllerTypes []reflect.Type // 存储已注册的控制器类型
}

// NewAutoRouter 创建一个新的自动路由注册器
func NewAutoRouter(router *Router) *AutoRouter {
	return &AutoRouter{
		router:          router,
		controllerTypes: make([]reflect.Type, 0),
	}
}


// RegisterController 注册控制器的所有方法为路由
// controllerPtr 必须是控制器的指针
func (ar *AutoRouter) RegisterController(controllerPtr common.ControllerInterface) {
	ar.mutex.Lock()
	defer ar.mutex.Unlock()

	// 获取控制器类型
	controllerType := reflect.TypeOf(controllerPtr)
	controllerName := controllerType.Elem().Name()

	// 提取控制器名称（去掉Controller后缀）
	basePath := strings.ToLower(strings.TrimSuffix(controllerName, "Controller"))

	// 获取控制器的值
	controllerValue := reflect.ValueOf(controllerPtr)

	// 遍历控制器的所有方法
	for i := 0; i < controllerType.NumMethod(); i++ {
		methodName := controllerType.Method(i).Name
		method := controllerType.Method(i)

		// 检查方法签名是否符合 http.HandlerFunc
		if method.Type.NumIn() == 3 {
			// 获取参数类型
			param1Type := method.Type.In(1)
			param2Type := method.Type.In(2)
			
			isHttpHandler := false
			// 安全地进行反射检查
			defer func() {
				if r := recover(); r != nil {
					log.Printf("恢复反射错误: %v", r)
					isHttpHandler = false
				}
			}()
			
			// http.ResponseWriter 是接口，*http.Request 是指针
			httpResponseWriterType := reflect.TypeOf((*http.ResponseWriter)(nil)).Elem()
			httpRequestPtrType := reflect.TypeOf((*http.Request)(nil))
			
			// 检查第一个参数是否实现了 http.ResponseWriter 接口
			// 检查第二个参数是否为 *http.Request 类型
			if (param1Type.Implements(httpResponseWriterType) || 
				(param1Type.Kind() == reflect.Ptr && param1Type.Elem().Implements(httpResponseWriterType))) && 
				param2Type == httpRequestPtrType {
				isHttpHandler = true
			}
			
			if isHttpHandler {
				// 解析HTTP方法和实际方法名
				httpMethod := "GET" // 默认使用GET方法
				actualMethodName := methodName

				// 检查方法名是否以HTTP方法为前缀（例如：GetUser, PostUser等）
				if len(methodName) > 3 {
					httpPrefix := methodName[:3]
					switch strings.ToUpper(httpPrefix) {
					case "GET":
						httpMethod = "GET"
						actualMethodName = methodName[3:]
					case "POST":
						httpMethod = "POST"
						actualMethodName = methodName[4:]
					case "PUT":
						httpMethod = "PUT"
						actualMethodName = methodName[3:]
					case "DELETE":
						httpMethod = "DELETE"
						actualMethodName = methodName[6:]
					}
				}

				// 生成路由路径
				routePath := "" // 避免重复的斜杠
				if basePath != "" {
					routePath = "/" + basePath
				}

				// 如果方法名不是Index，则添加到路径中
				if actualMethodName != "Index" && actualMethodName != "" {
					// 将驼峰命名转换为下划线分隔
					snakeCaseName := toSnakeCase(actualMethodName)
					routePath += "/" + snakeCaseName
				}

				// 确保路径以斜杠开头
				if routePath == "" {
					routePath = "/"
				} else if routePath[0] != '/' {
					routePath = "/" + routePath
				}

				// 创建HandlerFunc
				handler := func(w http.ResponseWriter, r *http.Request) {
					method.Func.Call([]reflect.Value{controllerValue, reflect.ValueOf(w), reflect.ValueOf(r)})
				}

				// 根据HTTP方法注册路由
				switch httpMethod {
				case "GET":
					ar.router.GET(routePath, handler)
				case "POST":
					ar.router.POST(routePath, handler)
				case "PUT":
					ar.router.PUT(routePath, handler)
				case "DELETE":
					ar.router.DELETE(routePath, handler)
				}

				log.Printf("已自动注册路由: %s %s -> %s.%s", httpMethod, routePath, controllerName, methodName)
			}
		}
	}
	
	// 保存控制器类型
	ar.controllerTypes = append(ar.controllerTypes, controllerType)
}

// toSnakeCase 将驼峰命名转换为下划线分隔的命名
func toSnakeCase(s string) string {
	var result strings.Builder
	for i, r := range s {
		if i > 0 && unicode.IsUpper(r) {
			result.WriteRune('_')
		}
		result.WriteRune(unicode.ToLower(r))
	}
	return result.String()
}

// RegisterControllers 批量注册多个控制器
func (ar *AutoRouter) RegisterControllers(controllers ...common.ControllerInterface) {
	for _, controller := range controllers {
		ar.RegisterController(controller)
	}
}

// GetControllerTypes 获取已注册的控制器类型列表
func (ar *AutoRouter) GetControllerTypes() []reflect.Type {
	ar.mutex.RLock()
	defer ar.mutex.RUnlock()
	// 返回副本以避免并发问题
	result := make([]reflect.Type, len(ar.controllerTypes))
	copy(result, ar.controllerTypes)
	return result
}

// RegisterAllControllersInPackage 自动扫描包目录并注册所有控制器
// packagePath 是控制器包的路径，如 "think/app/controller"
func (ar *AutoRouter) RegisterAllControllersInPackage(packagePath string) error {
	// 获取当前工作目录
	cwd, err := os.Getwd()
	if err != nil {
		return err
	}

	// 构建完整的控制器目录路径
	controllerDir := filepath.Join(cwd, packagePath)

	// 读取控制器目录下的所有Go文件
	files, err := ioutil.ReadDir(controllerDir)
	if err != nil {
		return err
	}

	// 查找Go文件中的控制器类型
	controllerRegex := regexp.MustCompile(`type\s+(\w+)Controller\s+struct`)

	// 临时存储找到的控制器类型
	var foundControllers []common.ControllerInterface

	// 遍历文件
	for _, file := range files {
		if file.IsDir() || !strings.HasSuffix(file.Name(), ".go") {
			continue
		}

		// 读取文件内容
		filePath := filepath.Join(controllerDir, file.Name())
		content, err := ioutil.ReadFile(filePath)
		if err != nil {
			log.Printf("读取文件失败 %s: %v", filePath, err)
			continue
		}

		// 使用正则表达式查找控制器定义
		matches := controllerRegex.FindAllSubmatch(content, -1)
		for _, match := range matches {
			if len(match) > 1 {
				controllerName := string(match[1]) + "Controller"
				// 尝试实例化控制器
				controllerInstance, err := instantiateController(packagePath, controllerName)
				if err == nil && controllerInstance != nil {
					foundControllers = append(foundControllers, controllerInstance)
					log.Printf("已发现控制器: %s", controllerName)
				}
			}
		}
	}

	// 注册所有找到的控制器
	ar.RegisterControllers(foundControllers...)
	return nil
}

// instantiateController 实例化控制器
func instantiateController(packagePath, controllerName string) (common.ControllerInterface, error) {
	// 由于Go的反射限制，我们需要使用已知的控制器类型映射
	// 这里使用工厂模式来实例化控制器
	controllerFactory := map[string]func() common.ControllerInterface{
		"IndexController": func() common.ControllerInterface { return &controller.IndexController{} },
		"UserController":  func() common.ControllerInterface { return &controller.UserController{} },
	}

	// 尝试从工厂中获取构造函数
	if constructor, exists := controllerFactory[controllerName]; exists {
		return constructor(), nil
	}

	return nil, nil
}
